#include"Socket.h"
#include<iostream>
#include<functional>
#include"sever.h"
#include"ThreadPool.h"
#include"MMySql.h"
#include"TcpConnection.h"
#include<unistd.h>
#include "dataProcess.h"
#include"DirContral.h"
#include<fstream>
#include<mutex>
#include<map>
#include<utility>

#define BUFFERSIZE 1024*20
std::mutex fileWriteMutex;
std::map<std::string,std::mutex> nameMutex;
// std::map<std::string,uint64_t> fileOffetReq;
// std::map<std::string,std::vector<std::vector<uint8_t>>> filedata;


namespace Data{
    void handleData(const Buffer &buffer, std::shared_ptr<TcpConnection> conn,MMySql *mysql){
        std::function<void()> task = [buffer,conn,mysql](){
            // std::cout<<"gongzuo1"<<std::this_thread::get_id()<<std::endl;
            CloudDrive::Packet packet;
            std::string str = buffer.returnBuffData();
            std::vector<uint8_t> data(str.begin(), str.end());
            if(!CloudDrive::deserialize(data, packet)){ return; }
            
            switch (packet.header.type) {
                //注册
                case CloudDrive::MessageType::REGISTER:{    
                    // 验证包体大小
                    CloudDrive::MesBack msgBack;
                    if (packet.body.size() < sizeof(CloudDrive::UserInfo)) {
                        std::cerr << "错误：包体大小不足！" << std::endl;
                        return; // 添加返回语句，防止后续内存操作
                    }
                    CloudDrive::UserInfo uInfo;
                    std::memcpy(&uInfo, packet.body.data(), sizeof(CloudDrive::UserInfo));
                    std::string userName = uInfo.userName;
                    std::string phone = uInfo.account;
                    std::string passWord = uInfo.password;
                    std::string email = uInfo.email;

                    msgBack.type =mysql->enroll(std::stoi(phone),userName,passWord,email);
                    Data::sendData(packet,msgBack,conn);
                    break;
                }
                //登陆
                case CloudDrive::MessageType::LOGIN:{
                    // 验证包体大小
                    CloudDrive::MesBack msgBack;
                    if (packet.body.size() < sizeof(CloudDrive::UserInfo)) {
                        std::cerr << "错误：包体大小不足！" << std::endl;
                        return; // 添加返回语句，防止后续内存操作
                    }
                    CloudDrive::UserInfo uInfo;
                    std::memcpy(&uInfo, packet.body.data(), sizeof(CloudDrive::UserInfo));
                    std::string phone = uInfo.account;
                    std::string passWord = uInfo.password;
                    //更改登陆信息
                    msgBack.type = mysql->Login(std::stoi(phone),passWord);
                    Sever::getinstance().addClntLinkConnection(phone,conn->getFd());
                    Data::sendData(packet,msgBack,conn);
                    break;
                }   
               //刷新好友列表
                case CloudDrive::MessageType::REFRESH_FRIEND:{
                    if (packet.body.size() < sizeof(CloudDrive::UserInfo)) {
                        std::cerr << "错误：包体大小不足！" << std::endl;
                        return; // 添加返回语句，防止后续内存操作
                    }
                    CloudDrive::UserInfo uInfo;
                    std::memcpy(&uInfo, packet.body.data(), sizeof(CloudDrive::UserInfo));
                    std::string phone = uInfo.account;
                    CloudDrive::MesBack msgBack = mysql->Refresh(std::stoi(phone));
                    Data::sendData(packet,msgBack,conn);
                    break;
                } 
                //添加好友
                case CloudDrive::MessageType::ADD_FRIEND:{
                    if (packet.body.size() < sizeof(CloudDrive::UserInfo)) {
                        std::cerr << "错误：包体大小不足！" << std::endl;
                        return; // 添加返回语句，防止后续内存操作
                    }
                    CloudDrive::UserInfo uInfo;
                    std::memcpy(&uInfo, packet.body.data(), sizeof(CloudDrive::UserInfo));
                    std::string phone = uInfo.account;
                    std::string friendPhone = uInfo.friendName;

                    std::map<std::string,int> clntLinkConnection =Sever::getinstance().getClntLinkConnection();
                    //用户不在线户或者不存在
                    if(clntLinkConnection.count(friendPhone) == 0) {
                        
                        uInfo.type = CloudDrive::MessageReturn::ADDFRIEND_NOTEXIST;
                        conn->enqueueSend(CloudDrive::makeUserPacket(packet,uInfo,0));
                        return;
                    }
                    //向添加的用户转发添加信息
                    std::map<int,std::shared_ptr<TcpConnection>> connection = Sever::getinstance().getConnection();

                    std::shared_ptr<TcpConnection> connFriend = connection[clntLinkConnection[friendPhone]];
                    //打包
                    packet.header.type = CloudDrive::MessageType::ADD_FRIEND_REQ;
                    CloudDrive::Packet pkt;
                    pkt = CloudDrive::makeUserPacket(packet,uInfo,0);
                    connFriend->enqueueSend(pkt);
                    break;
                }
               //添加好友对面回复
                case CloudDrive::MessageType::ADD_FRIEND_REQ:{
                    if (packet.body.size() < sizeof(CloudDrive::UserInfo)) {
                        std::cerr << "错误：包体大小不足！" << std::endl;
                        return; // 添加返回语句，防止后续内存操作
                    }
                    CloudDrive::UserInfo uInfo;
                    packet.header.type = CloudDrive::MessageType::ADD_FRIEND;

                    std::memcpy(&uInfo, packet.body.data(), sizeof(CloudDrive::UserInfo));
                    std::string userName = uInfo.account;
                    std::string friendPhone = uInfo.friendName;

                    if(uInfo.type == CloudDrive::MessageReturn::ADDFRIEND_AGREE){
                        mysql->addFriend(std::stoi(userName),std::stoi(friendPhone));
                    }   

                    std::map<std::string,int> clntLinkConnection =Sever::getinstance().getClntLinkConnection();
                    if(clntLinkConnection.count(friendPhone) == 0) { return;}
                    std::map<int,std::shared_ptr<TcpConnection>> connection = Sever::getinstance().getConnection();
                    std::shared_ptr<TcpConnection> connFriend = connection[clntLinkConnection[friendPhone]];

                    connFriend->enqueueSend(CloudDrive::makeUserPacket(packet,uInfo,0));

                    std::string phone = uInfo.account;
                    CloudDrive::MesBack msgBack = mysql->Refresh(std::stoi(phone));
                    Data::sendData(packet,msgBack,conn);
                    break;
                }
                //删除好友
                case CloudDrive::MessageType::REMOVE_FRIEND:{
                    if (packet.body.size() < sizeof(CloudDrive::UserInfo)) {
                        std::cerr << "错误：包体大小不足！" << std::endl;
                        return; // 添加返回语句，防止后续内存操作
                    }
                    CloudDrive::UserInfo uInfo;
                    std::memcpy(&uInfo, packet.body.data(), sizeof(CloudDrive::UserInfo));
                    std::string phone = uInfo.account;
                    std::string friendPhone = uInfo.friendName;
                    uInfo.type = mysql->deletFriend(std::stoi(phone),std::stoi(friendPhone));
                    conn->enqueueSend(CloudDrive::makeUserPacket(packet,uInfo,0));

                    std::map<std::string,int> clntLinkConnection =Sever::getinstance().getClntLinkConnection();
                    if(clntLinkConnection.count(friendPhone) == 0) { return;}
                    std::map<int,std::shared_ptr<TcpConnection>> connection = Sever::getinstance().getConnection();
                    std::shared_ptr<TcpConnection> connFriend = connection[clntLinkConnection[friendPhone]];
                    packet.header.type = CloudDrive::MessageType::REMOVE_FRIEND_REQ;
                    connFriend->enqueueSend(CloudDrive::makeUserPacket(packet,uInfo,0));
                    break;
                }
                // 转发好友消息
                case CloudDrive::MessageType::SEND_FRIEND_MSG:{
                     if (packet.body.size() < sizeof(CloudDrive::UserInfoMsg)) {
                        std::cerr << "错误：包体大小不足！" << std::endl;
                        return; // 添加返回语句，防止后续内存操作
                    }
                    CloudDrive::UserInfoMsg uIfoMsg;

                    std::memcpy(&uIfoMsg, packet.body.data(), sizeof(CloudDrive::UserInfoMsg));
                    std::string phone = uIfoMsg.account;
                    std::string friendPhone = uIfoMsg.friendName;

                    std::map<std::string,int> clntLinkConnection =Sever::getinstance().getClntLinkConnection();
                    if(clntLinkConnection.count(friendPhone) == 0) { return;}
                    std::map<int,std::shared_ptr<TcpConnection>> connection = Sever::getinstance().getConnection();
                    std::shared_ptr<TcpConnection> connFriend = connection[clntLinkConnection[friendPhone]];
                    connFriend->enqueueSend(packet);
                    break;
                }   
                //刷新文件列表
                case CloudDrive::MessageType::REFRESH_FILELIST:{
                    if (packet.body.size() < sizeof(CloudDrive::UserInfoMsg)) {
                        std::cerr << "错误：包体大小不足！" << std::endl;
                        return; // 添加返回语句，防止后续内存操作
                    }
                    CloudDrive::UserInfoMsg uIfoMsg;
                    std::memcpy(&uIfoMsg, packet.body.data(), sizeof(CloudDrive::UserInfoMsg));

                    CloudDrive::MesBackFile fileListInfo =  DirContral::getInstance().getFileList(uIfoMsg.msg);
                    conn->enqueueSend(CloudDrive::makeRetFileListPacket(packet,fileListInfo,1));
                    break;
                }
                //创建文件夹
                case CloudDrive::MessageType::NEWFILEDIR:{
                    if (packet.body.size() < sizeof(CloudDrive::UserInfoMsg)) {
                        std::cerr << "错误：包体大小不足！" << std::endl;
                        return; // 添加返回语句，防止后续内存操作
                    }
                    CloudDrive::UserInfoMsg uIfoMsg;
                    std::memcpy(&uIfoMsg, packet.body.data(), sizeof(CloudDrive::UserInfoMsg));
                    std::cout<<uIfoMsg.msg<<std::endl;

                    CloudDrive::MesBack msg;
                    msg.type = DirContral::getInstance().creatNewFolder(uIfoMsg.msg);
                    conn->enqueueSend(CloudDrive::makeRetPacket(packet,msg,1));

                    break;
                }
                //删除文件夹
                case CloudDrive::MessageType::DELETEFILE:{                 
                    if (packet.body.size() < sizeof(CloudDrive::UserInfoMsg)) {
                        std::cerr << "错误：包体大小不足！" << std::endl;
                        return; // 添加返回语句，防止后续内存操作
                    }
                    CloudDrive::UserInfoMsg uIfoMsg;
                    std::memcpy(&uIfoMsg, packet.body.data(), sizeof(CloudDrive::UserInfoMsg));
                    CloudDrive::MesBack msg;
                    msg.type = DirContral::getInstance().deleteFolder(uIfoMsg.msg);

                    conn->enqueueSend(CloudDrive::makeRetPacket(packet,msg,1));
                    break;
                }
                //上传文件
                case CloudDrive::MessageType::UPLOADFILE:{
                    if (packet.body.size() < sizeof(CloudDrive::FileInfo)) {
                        std::cerr << "错误：包体大小不足！" << std::endl;
                        return; // 添加返回语句，防止后续内存操作
                    }
                    CloudDrive::FileInfo fileInfo;
                    std::memcpy(&fileInfo,packet.body.data(),sizeof(CloudDrive::FileInfo));

                    //解析出数据
                    const size_t dataOffset = sizeof(CloudDrive::FileInfo);
                    const size_t dataSize = packet.body.size()-dataOffset;

                    std::vector<uint8_t> data1(packet.body.begin()+dataOffset,packet.body.begin()+dataOffset+dataSize);

                    std::string path = fileInfo.filePath;
                    std::string filenam = fileInfo.filename;
                    std::string str = path+"/"+filenam;
                    {
                        std::lock_guard<std::mutex> lock(fileWriteMutex);
                        if (nameMutex.find(str) == nameMutex.end()) {
                            nameMutex.emplace(
                                std::piecewise_construct,
                                std::forward_as_tuple(str),
                                std::forward_as_tuple()
                            );
                        }
                    }
                    // 如果写入成功回传数据
                    std::cout<<fileInfo.filename<<"\t"<<fileInfo.dataBlockId<<std::endl;
                    packet.header.type = CloudDrive::MessageType::UPLOADFILE_ACK;
                    conn->enqueueSend(CloudDrive::makeFileInfoPacket(packet,fileInfo,packet.header.session_id));
                   DirContral::getInstance() .writeDataToFile(str,data1,fileInfo.offset,nameMutex.at(str),true);
                    break;
                }
                //上传完成
                case CloudDrive::MessageType::UPLOADFILE_FUNISH:{
                    if (packet.body.size() < sizeof(CloudDrive::FileInfo)) {
                        std::cerr << "错误：包体大小不足！" << std::endl;
                        return; // 添加返回语句，防止后续内存操作
                    }
                    // CloudDrive::FileInfo fileInfo;
                    // std::memcpy(&fileInfo,packet.body.data(),sizeof(CloudDrive::FileInfo));
                    // std::vector<std::vector<uint8_t>> data;
                    // {
                    //     std::lock_guard<std::mutex> lock(fileWriteMutex);
                    //     data = filedata[fileInfo.filename];
                    //     filedata.erase(fileInfo.filename);
                    // }
                    // writeFileAll(fileInfo.filePath,data);
                    break;
                }
                //下载文件
                case CloudDrive::MessageType::DOWNFILE:{
                    if(packet.body.size()<sizeof(CloudDrive::FileInfo)){
                        std::cout<<"包体大小不足"<<std::endl;
                    }
                    CloudDrive::FileInfo Fi;
                    std::memcpy(&Fi,packet.body.data(),sizeof(CloudDrive::FileInfo));
                    std::string path = Fi.filePath;
                    std::string filenam = Fi.filename;
                    std::string fileIdeter = Fi.fileIdentfir;
                    std::cout<<"identr"<<fileIdeter.size()<<std::endl;
                    DirContral::getInstance().downLoadFile(filenam,path,Fi.fileIdentfir,conn);
                    break;
                }
                //下载暂停
                case CloudDrive::MessageType::DOWNFILE_PAUSE:{
                    if(packet.body.size()<sizeof(CloudDrive::FileInfo)){
                        std::cout<<"包体大小不足"<<std::endl;
                    }
                    CloudDrive::FileInfo Fi;
                    std::memcpy(&Fi,packet.body.data(),sizeof(CloudDrive::FileInfo));
                    DirContral::getInstance().fileDownSet("Pause",Fi.fileIdentfir);
                    break;
                }

                //下载继续
                case CloudDrive::MessageType::DOWNFILE_CONTINUE:{
                    if(packet.body.size()<sizeof(CloudDrive::FileInfo)){
                        std::cout<<"包体大小不足"<<std::endl;
                    }
                    CloudDrive::FileInfo Fi;
                    std::memcpy(&Fi,packet.body.data(),sizeof(CloudDrive::FileInfo));
                    DirContral::getInstance().fileDownSet("Continue",Fi.fileIdentfir);
                    break;
                }
                
                //下载取消
                case CloudDrive::MessageType::DOWNFILE_CANCEL:{
                    if(packet.body.size()<sizeof(CloudDrive::FileInfo)){
                        std::cout<<"包体大小不足"<<std::endl;
                    }
                    CloudDrive::FileInfo Fi;
                    std::memcpy(&Fi,packet.body.data(),sizeof(CloudDrive::FileInfo));
                    DirContral::getInstance().fileDownSet("Cancell",Fi.fileIdentfir);
                    break;
                }
                
                default:
                    break;
            } 
        };
        task(); // 执行任务
    }
    void sendData(const CloudDrive::Packet packet, CloudDrive::MesBack msgBack, std::shared_ptr<TcpConnection> conn)
    {
        // //回复消
        CloudDrive::Packet ptk;
        ptk = CloudDrive::makeRetPacket(packet,msgBack,ptk.header.session_id);
        conn->enqueueSend(ptk);
    }
}
